#include "database.h"

#include <QDir>
#include <QFile>

DataBase::DataBase()
{
    m_Path = "..//config";
    m_Name = "iris.db";
    m_dbName = "iris";

    m_iIsInizFlag = false;
}

bool DataBase::initDbAndTable()
{
    //check
    QDir dir(m_Path);
    if( !dir.exists())
    {
        if(!dir.mkdir(m_Path) )
        {return false;}
    }
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", m_dbName);
    db.setDatabaseName(m_Path + "//" + m_Name);
    if( !db.open())
    {
        qDebug() << db.lastError().text();
        return false;
    }
    m_db = db;
    m_query = QSqlQuery(m_db);

    m_iIsInizFlag = true;
    qDebug() << "Create DB Successful";

    if(! m_query.exec(CREATE_TABLE_REPOSITORY))
    {
        qWarning() << m_query.lastError().text();
        return false;
    }
    if(! m_query.exec(CREATE_TABLE_CHARACTOR))
    {
        qWarning() << m_query.lastError().text();
        return false;
    }
    qDebug() << "Create Table Successful";
    return true;
}

bool DataBase::initDriver()
{
    //check
    QDir dir(m_Path);
    if( !dir.exists())
    {
        if(!dir.mkdir(m_Path) )
        {return false;}
    }
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", m_dbName);
    db.setDatabaseName(m_Path + "//" + m_Name);
    if( !db.open())
    {
        qDebug() << db.lastError().text();
        return false;
    }
    m_db = db;
    m_query = QSqlQuery(m_db);

    m_iIsInizFlag = true;
    qDebug() << "Init Driver Successful";
    return doCheck();
}

bool DataBase::createConnection()
{
    m_db = QSqlDatabase::database(m_dbName);
    if( !m_db.isOpen())
    {
        qDebug() << m_db.lastError().text();
        return false;
    }
    m_query = QSqlQuery(m_db);
    m_iIsInizFlag = true;
    qDebug() << "Create Connection Successful";
    return doCheck();
}

bool DataBase::insertCharacotr(QString pathName,
            CharacterVector* pVecCharactor,int nSize)
{
    if( nullptr == pVecCharactor)
    {
        qWarning() << "nullptr";
        return false;
    }

    if( !doCheck())
    {
        return false;
    }

    QString execCmd;
    int repository_id = 0;
    int charactor_id = 0;

    if( !getNewId(TABLE_REPOSITORY_INFO,repository_id))
    {
        return false;
    }
    execCmd = "insert into " TABLE_REPOSITORY_INFO " values("
            + QString::fromStdString(std::to_string(repository_id))
            + ",\'" + pathName + "\'"
            ",\'default\'"
            ")";
    qDebug() << "cmd:" << execCmd;
    if(!m_query.exec(execCmd))
    {
        qWarning() << m_query.lastError().text();
        return false;
    }

    if( !getNewId(TABLE_CHARACTOR_RECORD,charactor_id))
    {
        return false;
    }
    execCmd = "insert into " TABLE_CHARACTOR_RECORD " values("
            "?, ?, ?, ?, ?, ?, ?, ?, ?)";
    qDebug() << "cmd:" << execCmd;
    if(! m_query.prepare(execCmd))
    {
        qWarning() << m_query.lastError().text();
        return false;
    }
    //insert all
    for(int index = 0; index < nSize; ++index)
    {
        int pos = 0;
        m_query.bindValue(pos++,charactor_id + index);
        m_query.bindValue(pos++,(pVecCharactor+index)->x);
        m_query.bindValue(pos++,(pVecCharactor+index)->y);
        m_query.bindValue(pos++,(pVecCharactor+index)->type);
        m_query.bindValue(pos++,(pVecCharactor+index)->top);
        m_query.bindValue(pos++,(pVecCharactor+index)->bottom);
        m_query.bindValue(pos++,(pVecCharactor+index)->left);
        m_query.bindValue(pos++,(pVecCharactor+index)->right);
        m_query.bindValue(pos++,repository_id);
        if(!m_query.exec())
        {
            qWarning() << m_query.lastError().text();
            return false;
        }
    }
    qDebug() << "Insert " << nSize << " successful";

    return true;
}

bool DataBase::queryRepository(RepositoryInfo_t *pRepository,
    int &nSize, int maxSize)
{
    if( nullptr == pRepository)
    {
        qWarning() << "nullptr";
        return false;
    }
    if( !doCheck())
    {
        return false;
    }

    QString execCmd;
    execCmd = "select * from " TABLE_REPOSITORY_INFO;
    qDebug() << "cmd:" << execCmd;
    if(! m_query.exec(execCmd))
    {
        qWarning() << m_query.lastError().text();
        return false;
    }

//    QSqlRecord rec = m_query.record();
//    nSize = rec.count();
//    qDebug() << "nRecord=" << nSize;
//    if(maxSize < nSize)
//    {
//        qDebug() << "Size change to " << maxSize <<
//            " from " << nSize;
//        nSize = maxSize;
//    }
    int index = 0;
    for(;m_query.next() && index < maxSize;++index)
    {
        int pos = 0;
        (pRepository+index)->id = m_query.value(pos++).toInt();
        (pRepository+index)->uri = m_query.value(pos++).toString();
        (pRepository+index)->name = m_query.value(pos++).toString();
    }
//    if(index < nSize)
//    {
//        qDebug() << "Size change to " << index <<
//            " from " << nSize;
//        nSize = index;
//    }
    nSize = index;
    qDebug() << "nRecord=" << nSize;

    return true;
}

bool DataBase::queryCharactor(int repository_id,
    CharacterVector *pVecCharactor, int &nSize,int maxSize)
{
    if( nullptr == pVecCharactor)
    {
        qWarning() << "nullptr";
        return false;
    }
    if( !doCheck())
    {
        return false;
    }

    QString execCmd;
    execCmd = "select * from " TABLE_CHARACTOR_RECORD
            " where repository_id=?";
    qDebug() << "cmd:" << execCmd;
    if(! m_query.prepare(execCmd))
    {
        qWarning() << m_query.lastError().text();
        return false;
    }
    m_query.bindValue(0,repository_id);
    if(!m_query.exec())
    {
        qWarning() << m_query.lastError().text();
        return false;
    }
//    QSqlRecord rec = m_query.record();
//    nSize = rec.count();
//    qDebug() << "nRecord=" << nSize;
//    if(maxSize < nSize)
//    {
//        qDebug() << "Size change to " << maxSize <<
//            " from " << nSize;
//        nSize = maxSize;
//    }
    int index = 0;
    for(;m_query.next() && index < maxSize;++index)
    {
        int pos = 1;
        (pVecCharactor+index)->x = m_query.value(pos++).toInt();
        (pVecCharactor+index)->y = m_query.value(pos++).toInt();
        (pVecCharactor+index)->type = m_query.value(pos++).toInt();
        (pVecCharactor+index)->top = m_query.value(pos++).toInt();
        (pVecCharactor+index)->bottom = m_query.value(pos++).toInt();
        (pVecCharactor+index)->left = m_query.value(pos++).toInt();
        (pVecCharactor+index)->right = m_query.value(pos++).toInt();
    }
//    if(index < nSize)
//    {
//        qDebug() << "Size change to " << index <<
//            " from " << nSize;
//        nSize = index;
//    }
    nSize = index;
    qDebug() << "nRecord=" << nSize;

    return true;
}

void DataBase::printCount(QString tableName)
{
    if( !doCheck())
    {
        return;
    }
    QString execCmd;
    execCmd = "select count(id) from " + tableName;
    qDebug() << "cmd:" << execCmd;
    if(!m_query.exec(execCmd))
    {
        qWarning() << m_query.lastError().text();
        return;
    }
    QSqlRecord rec = m_query.record();
    int nSize = rec.count();
    int index = 0;
    for(;m_query.next() && index < nSize;++index)
    {
        qDebug() << "Table " << tableName <<
            " current count=" << m_query.value(0).toInt();
        break;
    }

    return;
}

bool DataBase::doCheck()
{
    if(!m_iIsInizFlag)
    {
        qWarning() << "Not init";
        return false;
    }
    if(!m_db.isValid())
    {
        qWarning() << "DB is invalid";
        return false;
    }
//    if(!m_query.isValid())
//    {
//        qWarning() << "Query is invalid";
//        return false;
//    }
    return true;
}

bool DataBase::getNewId(QString table, int &id)
{
    if( !doCheck())
    {
        return false;
    }
    QString execCmd;
    execCmd = "select count(id) from " + table;
    qDebug() << "cmd:" << execCmd;
    if(!m_query.exec(execCmd))
    {
        qWarning() << m_query.lastError().text();
        return false;
    }
    int nCount = 0;
    for(;m_query.next();)
    {
        nCount = m_query.value(0).toInt();
        break;
    }
    if(nCount)
    {
        execCmd = "select id from " + table +
            " order by id limit 1 offset " +
            QString::fromStdString(std::to_string(nCount-1));
        qDebug() << "cmd:" << execCmd;
        if(!m_query.exec(execCmd))
        {
            qWarning() << m_query.lastError().text();
            return false;
        }
        for(;m_query.next();)
        {
            id = m_query.value(0).toInt();
            break;
        }
    }

    ++id;
    qDebug() << "New id is " << id;
    return true;
}

